home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
linuxcon.000
/
linuxcon
/
linuxconf-1.6
/
misc
/
popen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-08-03
|
3KB
|
194 lines
#pragma implementation
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include "misc.h"
#include "popen.h"
PUBLIC POPEN::POPEN(const char *command)
{
pid = -1;
status = -1;
int fdout[2];
int fderr[2];
if (pipe(fdout)!=-1 && pipe(fderr)!=-1){
pid = fork();
if (pid == 0){
close (fdout[0]);
close (fderr[0]);
dup2 (fdout[1],1);
dup2 (fderr[1],2);
close (fdout[1]);
close (fderr[1]);
setuid (geteuid());
int ret = system (command);
_exit (ret);
}
close (fdout[1]);
close (fderr[1]);
fds.out = fdout[0];
fds.err = fderr[0];
}
}
PUBLIC POPEN::~POPEN()
{
if (pid != -1){
kill (pid,SIGTERM);
waitend();
}
close (fds.out);
close (fds.err);
}
/*
Wait until the process is really dead and recover its end status
*/
PRIVATE void POPEN::waitend ()
{
while (1){
int code = ::wait(&status);
if (code == pid) break;
fprintf (stderr,"code = %d\n",code);
}
pid = -1;
}
/*
Return != 0 if the pipe is corretly opened
*/
PUBLIC int POPEN::isok()
{
return pid != -1;
}
PRIVATE void POPEN::readif (struct fd_set *in, int fd, SSTRING &buf)
{
if (FD_ISSET(fd,in)){
char bufread[10000];
int len = read (fd,bufread,sizeof(bufread)-1);
if (len > 0){
bufread[len] = '\0';
buf.append (bufread);
}else{
// end of process
waitend();
}
}
}
/*
Wait for anything to be available from the child process
Return -1 if any error.
Return 0 if the timeout has elapsed.
Return 1 if there is some data to read
*/
PUBLIC int POPEN::wait(int timeout)
{
int ret = -1;
if (pid != -1){
struct fd_set in;
FD_ZERO(&in);
FD_SET (fds.out,&in);
FD_SET (fds.err,&in);
struct timeval tim;
tim.tv_usec = 0;
tim.tv_sec = timeout;
int maxfd = fds.err > fds.out ? fds.err : fds.out;
ret = select (maxfd+1,&in,NULL,NULL,&tim);
readif (&in,fds.out,outbuf);
readif (&in,fds.err,errbuf);
}
return ret;
}
/*
Return the status code of the ending process
*/
PUBLIC int POPEN::getstatus()
{
return status;
}
/*
Read one complete line or up to size byte in "line".
If there is no complete line, nothing is read
*/
PRIVATE int POPEN::readline (char *line, int size, SSTRING &buf)
{
char *begin = line;
const char *pt = buf.get();
while (1){
if (*pt == '\0'){
if (pid == -1){
*line = '\0';
buf.setfrom ("");
}else{
*begin = '\0';
}
break;
}else{
char carac = *pt++;
*line++ = carac;
size--;
if (size == 0 || carac == '\n'){
buf.setfrom (pt);
*line = '\0';
break;
}
}
}
return line > begin ? 0 : -1;
}
/*
Read one line of stderr if available (won't block).
*/
PUBLIC int POPEN::readerr (char *line, int size)
{
return readline (line,size,errbuf);
}
/*
Read one line of stdout if available (won't block).
*/
PUBLIC int POPEN::readout (char *line, int size)
{
return readline (line,size,outbuf);
}
#ifdef TEST
int simul_isdemo(){return 0;}
int revision;
int main (int argc, char *argv[])
{
if (argc > 1){
char buf[1000];
char *pt = buf;
for (int i=1; i<argc; i++){
pt += sprintf (pt,"%s ",argv[i]);
}
printf ("execute la commande :%s:\n",buf);
POPEN p(buf);
while (p.isok()){
if (p.wait(10)>0){
while (p.readout(buf,sizeof(buf)-1)!=-1){
fputs (buf,stdout);
}
}else{
break;
}
}
}
return 0;
}
#endif